package org.ihelpuoo.weboo.upload.action;

import java.io.File;
import java.util.Calendar;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.log4j.Logger;
import org.ihelpuoo.filepool.FilePool;
import org.ihelpuoo.io.FileUtils;
import org.ihelpuoo.lang.InitializeException;
import org.ihelpuoo.lang.LoaderException;
import org.ihelpuoo.lang.NutException;
import org.ihelpuoo.lang.ObjectUtils;
import org.ihelpuoo.lang.StringUtils;
import org.ihelpuoo.orm.III;
import org.ihelpuoo.parser.segment.CharSegment;
import org.ihelpuoo.parser.segment.Segment;
import org.ihelpuoo.util.Properties;
import org.ihelpuoo.weboo.WebooUtils;
import org.ihelpuoo.weboo.module.ActionConfig;
import org.ihelpuoo.weboo.module.ActionContext;
import org.ihelpuoo.weboo.module.ModuleContext;
import org.ihelpuoo.weboo.upload.FileBean;
import org.ihelpuoo.weboo.upload.FileItem;
import org.ihelpuoo.weboo.upload.Upload;
import org.ihelpuoo.weboo.upload.index.IndexMaker;
import org.ihelpuoo.weboo.upload.index.IndexMakerFactory;

public class IndexedFileUploadAction extends FileUploadAction
{
	private static Logger		log	= Logger.getLogger(IndexedFileUploadAction.class);

	private FilePool			filePool;
	private FilePool			indexPool;
	private IndexMakerFactory	makers;
	private int					width;
	private int					height;

	private synchronized void initIndexPool(ModuleContext context, ActionConfig config,
			HttpServletRequest request) throws InitializeException, LoaderException, NutException
	{
		if (null == indexPool)
		{
			String name = config.getPropertyValue(context.getConfig().getStringTrimed(
					"INDEX_POOL_NAME"));
			Properties p = context.nut().getConfig(name);
			Segment seg = new CharSegment(p.getStringTrimed("home"));
			seg.set("appRoot",request.getSession().getServletContext().getRealPath("/"));
			p.setProperty("home",seg.toString());
			indexPool = (FilePool)context.nut().getFactory(p);
		}
	}

	private synchronized void initFilePool(ModuleContext context, ActionConfig config,
			HttpServletRequest request) throws InitializeException, LoaderException, NutException
	{
		if (null == filePool)
		{
			String name = config.getPropertyValue(context.getConfig().getStringTrimed(
					"FILE_POOL_NAME"));
			Properties p = context.nut().getConfig(name);
			Segment seg = new CharSegment(p.getStringTrimed("home"));
			seg.set("appRoot",request.getSession().getServletContext().getRealPath("/"));
			p.setProperty("home",seg.toString());
			filePool = (FilePool)context.nut().getFactory(p);
		}
	}

	private void init(ModuleContext context, ActionConfig config, HttpServletRequest request)
			throws NutException, LoaderException
	{
		if (null == filePool)
			initFilePool(context,config,request);
		if (null == indexPool)
			initIndexPool(context,config,request);
		if (null == makers)
		{
			makers = IndexMakerFactory.me(context.nut());
			width = Integer.parseInt(config.getPropertyValue("width"));
			height = Integer.parseInt(config.getPropertyValue("height"));
		}
	}

	@Override
	protected void execute(ActionContext context, Map<String, Object> params)
	{
		try
		{
			init(context.getModuleContext(),context.getActionConfig(),context.getRequest());
			String paramName = context.properties().getString("param_name");
			if (null == paramName)
				throw new Exception("Expect a param name in action config to indicate the file part!");
			if (null == params)
				throw new Exception("HttpRequest params is empty!");
			FileItem fi = (FileItem)params.get(paramName);
			if (fi.getFile().length() == 0)
			{
				FileUtils.deleteFile(fi.getFile());
				throw new Exception("You upload a 0k file!");
			}
			Class beanType = context.properties().getObjectType();

			if (null != beanType)
			{
				FileBean bean = (FileBean)ObjectUtils.newInstance(beanType);

				bean = (FileBean)context.pojo().fetch(params,bean,null,null);
				/*
				 * Update bean 
				 */
				bean = updateFileBean(context,fi,bean);

				bean = (FileBean)context.pojo().save(bean,null,null);

				if (bean.getId() <= III.DEFAULT_OBJECT_ID)
					throw new Exception(context.getMessage("upload.e.nullid"));
				if (null == fi)
					throw new Exception(context.getMessage("upload.e.nullparam") + " \""
							+ paramName + "\"");
				if (!fi.getFile().exists())
					throw new Exception(context.getMessage("upload.e.nulltempfile") + " \""
							+ fi.getFile().getPath() + "\"");

				File f = filePool.moveFileToPool(bean.getId(),fi.getFile());
				// create index
				/*
				 * If can find the image IndexMaker make the index
				 */
				File icon = indexPool.getFile(bean.getId(),Upload.ICON_IMG_TYPE);
				IndexMaker maker = makers.getMaker(f);
				if (null == maker)
					throw new Exception(context.getMessage("upload.e.nullmaker"));
				if (log.isDebugEnabled())
					log.debug("create thumbnail -> w:" + width + "   h:" + height);
				maker.make(f,icon,width,height);
				if (log.isDebugEnabled())
					log.debug("write response...");
				// done for create index
				Segment seg = context.createPattern(context.properties().getString(
						"succeed_segment"));
				WebooUtils.formatSegment(context,seg);
				context.getResponse().getWriter().write(seg.toString());
				context.getResponse().flushBuffer();
			}
			else
				throw new Exception(context.getMessage("upload.e.nullbean"));
		}
		catch (Exception e)
		{
			try
			{
				Segment seg = context.createPattern(context.properties()
						.getString("failed_segment"));
				WebooUtils.formatSegment(context,seg);
				seg.set("message",e.getMessage());
				context.getResponse().getWriter().write(seg.toString());
				context.getResponse().flushBuffer();
			}
			catch (Exception e1)
			{
				log.error(e1.toString());
			}
		}
	}

	protected FileBean updateFileBean(ActionContext context, FileItem fi, FileBean bean)
			throws Exception
	{
		Calendar now = Calendar.getInstance();
		if (StringUtils.isBlank(bean.getName()))
			bean.setName(fi.getOriginalName());
		bean.setExtension(fi.getExtension());
		bean.setCreateTime(now);
		bean.setLastModifiedTime(now);
		bean.setContentType(fi.getContentType());
		return bean;
	}
}
